import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;

public aspect Cache {
	// Method--------Args----Result
	private Map<String, Map<List<Object>, Object>> cache = new HashMap<String, Map<List<Object>, Object>>();

	pointcut caching():
		call(@Cacheable * *(..));

	Object around(): caching(){
		String method = thisJoinPoint.getSignature().toString();
		Object[] args = thisJoinPoint.getArgs();
		List<Object> deepMapKey = new ArrayList<Object>();
		for (Object arg : args){
			deepMapKey.add(arg);
		}
		Object result;
		if (cache.containsKey(method)) {
			// La cache ya contiene el metodo cacheado
			Map<List<Object>, Object> deepMap = cache.get(method);
			if (deepMap.containsKey(deepMapKey)) {
				//La cache tiene el resultado de ese metodo
				result = deepMap.get(deepMapKey);
				System.out.println("Se accedio a la cache por el valor "
						+ result);
			}
			else{
				//No tiene los argumentos cacheados
				result = proceed();
				deepMap.put(deepMapKey, result);
			}
		} else {
			result = proceed();
			System.out.println("Cacheando: " + args + " " + result);
			// Aca tengo que guardar la signatura y el resultado
			Map<List<Object>, Object> newDeepMap = new HashMap<List<Object>, Object>();
			newDeepMap.put(deepMapKey, result);
			cache.put(method, newDeepMap);
		}
		return result;
	}

	public void cleanCache(String method){
		this.cache.remove(method);
	}
	
	public Map<List<Object>, Object> getCache(String method){
		return this.cache.get(method);
	}
	
}
